<?php

namespace Kangcg\Application\Security;

use Kangcg\Application\Helper\HelperFunc;

/**
 * Class Mcrypt
 * @package Kang\Libs\Helper\Security
 */
class Mcrypt implements SecurityInterface
{
    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string cipher 加密方式 MCRYPT_RIJNDAEL_128
     * @param string mode 模式 MCRYPT_MODE_CBC //MCRYPT_MODE_CBC MCRYPT_MODE_ECB MCRYPT_MODE_NOFB MCRYPT_MODE_OFB MCRYPT_MODE_STREAM
     * @return Mcrypt
     */
    public function __construct(array $config)
    {
        $this->init($config);
    }

    /**
     * 要加密的字符
     * @param string|array $encrypted
     * @return bool|false|string
     */
    public function encode($encrypted, $isUsePublic = false)
    {
        $encrypted = is_array($encrypted) ? json_encode($encrypted, JSON_UNESCAPED_UNICODE) : $encrypted;
        try {
            return mcrypt_encrypt($this->_config['cipher'], $this->_config['key'], $encrypted, $this->_config['mode'], $this->_config['iv']);
        } catch (\Exception $exception) {
            return $this->setError($exception->getMessage());
        }
    }

    /**
     * 获取解密结果
     * @param string $encrypted
     * @return bool|string
     */
    public function decode(string $encrypted, $isUsePublic = false)
    {
        try {
            $result = mcrypt_decrypt($this->_config['cipher'], $this->_config['key'], $encrypted, $this->_config['mode'], $this->_config['iv']);;
            return $result ? $result : mcrypt_decrypt($this->_config['cipher'], $this->_config['key'], base64_decode($encrypted), $this->_config['mode'], $this->_config['iv']);;
        } catch (\Exception $exception) {
            return $this->setError($exception->getMessage());
        }
    }

    /**
     * @return string
     */
    public function getEncryption(): string
    {
        return 'aes';
    }

    /**
     * @param null $key
     * @return array|mixed|string
     */
    public function getConfig($key = null)
    {
        return $key === null ? $this->_config : ($this->_config[$key] ?? '');
    }

    /**
     * @param string $str
     * @return string
     */
    public function sign(string $str)
    {
        return md5($str);
    }

    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string cipher 加密方式
     * @return Mcrypt
     */
    public static function getInstall(array $config = [])
    {
        if (self::$_install === null) {
            self::$_install = new self($config);
        }

        return self::$_install;
    }

    /**
     * @param array $config
     * @param string key 密匙
     * @param string iv 必须16位
     * @param string cipher 加密方式
     * @return Mcrypt
     */
    public function init(array $config)
    {
        $this->_config['key'] = $config['key'];
        $this->_config['iv'] = HelperFunc::stringConstPadding($config['iv'], 16);
        $this->_config['cipher'] = $config['cipher'] ?? MCRYPT_RIJNDAEL_128;
        $this->_config['mode'] = $config['cipher'] ?? MCRYPT_MODE_CBC;
        return $this;
    }

    private function setError($error)
    {
        $this->_error = $error;
        return false;
    }

    public function getError()
    {
        return $this->_error;
    }

    private $_error = null;
    private $_config = [];
    private static $_install = null;
}
